package utils

import (
	"fmt"
	"github.com/bwmarrin/snowflake"
	global2 "longmen/server/config/global"
	"longmen/server/pkg/db/mysql/models/models_sports"
	"sync"
)

var instance *ShardingBatchCreate
var once sync.Once

func GetShardingBatchCreateInstance() *ShardingBatchCreate {
	once.Do(func() {
		snowflakeNodes := make([]*snowflake.Node, 1024)
		for i := int64(0); i < 1024; i++ {
			n, err := snowflake.NewNode(i)
			if err != nil {
				global2.Log.Fatalf("init snowflake node error, %v", err)
			}
			snowflakeNodes[i] = n
		}
		instance = &ShardingBatchCreate{
			snowflakeNodes: snowflakeNodes,
		}
	})
	return instance
}

type ShardingBatchCreate struct {
	snowflakeNodes []*snowflake.Node
}

func (s ShardingBatchCreate) GenId(node int) int64 {
	return s.snowflakeNodes[node].Generate().Int64()
}

func (s ShardingBatchCreate) GetShard(id int, shardCount int) int {
	return id % shardCount
}

func (s ShardingBatchCreate) CreteFootballOdds(odds []models_sports.FootballOdds, batchSize int) {
	if len(odds) == 0 {
		return
	}
	rawSql := `INSERT INTO db_football_odds
(id,match_id,company_id,exponential_type,exponential_score,match_status,odds_status,odds1,odds2,odds3,change_time,competition_time) 
VALUES %s  `

	// ON DUPLICATE KEY UPDATE match_id=VALUES(match_id),company_id=VALUES(company_id),
	//exponential_type=VALUES(exponential_type),exponential_score=VALUES(exponential_score),
	//match_status=VALUES(match_status),odds_status=VALUES(odds_status),
	//odds1=VALUES(odds1),odds2=VALUES(odds2),odds3=VALUES(odds3),
	//change_time=VALUES(change_time),competition_time=VALUES(competition_time);
	tplSql := "(%d,%d, %d, '%s', '%s', %d, %d, %s,%s,%s,%d,'%s')"
	valSql := ""
	count := 0
	totalCount := 0
	total := len(odds)
	for _, odd := range odds {
		totalCount++
		sfn := s.snowflakeNodes[s.GetShard(odd.MatchId, 256)]
		temp := fmt.Sprintf(tplSql,
			sfn.Generate().Int64(),
			odd.MatchId,
			odd.CompanyId,
			odd.ExponentialType,
			odd.ExponentialScore,
			odd.MatchStatus,
			odd.OddsStatus,
			odd.Odds1.String(),
			odd.Odds2.String(),
			odd.Odds3.String(),
			odd.ChangeTime,
			odd.CompetitionTime,
		)

		if count == batchSize {
			valSql += temp
			sql := fmt.Sprintf(rawSql, valSql)
			err := global2.SportSharding().Exec(sql).Error
			if err != nil {
				global2.Log.Error("football odds : ", err)
			}
			sql = ""
			valSql = ""
			count = 0
		} else {
			if totalCount == total {
				valSql += temp
			} else {
				valSql += temp + ","
			}
		}
		count++
	}
	if count > 0 {
		sql := fmt.Sprintf(rawSql, valSql)
		err := global2.SportSharding().Exec(sql).Error
		if err != nil {
			global2.Log.Error("football odds : ", err)
		}
	}
}

func (s ShardingBatchCreate) CreteBasketballOdds(odds []models_sports.BasketballOdds, batchSize int) {
	if len(odds) == 0 {
		return
	}
	rawSql := `INSERT INTO db_basketball_odds
(id,match_id,company_id,exponential_type,exponential_score,match_status,odds_status,odds1,odds2,odds3,change_time,competition_time) 
VALUES %s  `

	// ON DUPLICATE KEY UPDATE match_id=VALUES(match_id),company_id=VALUES(company_id),
	//exponential_type=VALUES(exponential_type),exponential_score=VALUES(exponential_score),
	//match_status=VALUES(match_status),odds_status=VALUES(odds_status),
	//odds1=VALUES(odds1),odds2=VALUES(odds2),odds3=VALUES(odds3),
	//change_time=VALUES(change_time),competition_time=VALUES(competition_time);
	tplSql := "(%d,%d, %d, '%s', '%s', %d, %d, %s,%s,%s,%d,'%s')"
	valSql := ""
	count := 0
	totalCount := 0
	total := len(odds)
	for _, odd := range odds {
		totalCount++
		sfn := s.snowflakeNodes[s.GetShard(odd.MatchId, 256)]
		temp := fmt.Sprintf(tplSql,
			sfn.Generate().Int64(),
			odd.MatchId,
			odd.CompanyId,
			odd.ExponentialType,
			odd.ExponentialScore,
			odd.MatchStatus,
			odd.OddsStatus,
			odd.Odds1.String(),
			odd.Odds2.String(),
			odd.Odds3.String(),
			odd.ChangeTime,
			odd.CompetitionTime,
		)

		if count == batchSize {
			valSql += temp
			sql := fmt.Sprintf(rawSql, valSql)
			err := global2.SportSharding().Exec(sql).Error
			if err != nil {
				global2.Log.Error("basketball odds err: ", err)
			}
			sql = ""
			valSql = ""
			count = 0
		} else {
			if totalCount == total {
				valSql += temp
			} else {
				valSql += temp + ","
			}
		}
		count++
	}
	if count > 0 {
		sql := fmt.Sprintf(rawSql, valSql)
		err := global2.SportSharding().Exec(sql).Error
		if err != nil {
			global2.Log.Error("basketball odds err1 : ", err)
		}
	}
}
